//
// Created by ChenJi on 2021/8/2.
//
#include <string.h>
#include <string_library.h>
#include "BC26Driver.h"
#include "UartController.h"

char *device_name = "1F2F3F4F";

char *bc26_cmd;
uint8_t bc26_cmd_len;

char *bc26_ValueStartPtr;
uint8_t bc26_value_len;

char *bc26_EndPtr;

char *bc26_newLineFlag = "\r\n";
char bc26_data_flag = '+';
char *bc26_data_start_flag = " ";
char *bc26_ATPlusFlag = "AT+";
char *bc26_OK_Flag = "OK";
char *bc26_ERROR_Flag = "ERROR";

char *server = "101.75.45.20";
uint16_t port = 1098;

char *sub_name = "hc/terminal/1/#";

char *keepAlive = "hc/keepalive/2";

uint8_t bc26_num_buf[20];


BC26_States bc26_states;
ParameterReader reader;
BC26_KeepAlive keepalive;
char *bc26_param_split_flag = ",";
char *bc26_cmd_QMTRECV = "QMTRECV";
char *bc26_cmd_QMTOPEN = "QMTOPEN";
char *bc26_cmd_QMTSTAT = "QMTSTAT";
char *bc26_cmd_QMTCONN = "QMTCONN";
char *bc26_cmd_CGATT = "CGATT";
char *bc26_cmd_QMTSUB = "QMTSUB";
char *bc26_cmd_QMTPUB = "QMTPUB";
char *bc26_cmd_IP = "IP";
char *bc26_cmd_CSQ = "CSQ";

uint8_t bc26_at_buffer[255];
uint8_t bc26_now_at_buffer_index;

BC26_Connect_MQTT_Setup bc26_setup;
BC26_MQTT_PublishManager publishManager;

void BC26_Init() {
    bc26_clearATBuffer();
    BC26_Setup_ResetAndSetup();
    bc26_states.Terminal_ready = 0;
}

void onUart3Message(uint8_t *message, uint16_t size) {
    //  sendMessageUart1(message,size);

    if (*(message + size - 1) != '\n' || *(message + size - 2) != '\r')
        return;//not end with /r/n
    if (*(message) == '\r' || *(message + 1) != '\n') {
        message++;
        message++;
    }
    if ((bc26_EndPtr = strstr((char *) message, bc26_newLineFlag)) == NULL) {
        return;
    }
    if (*(message) == bc26_data_flag) {
        if ((bc26_ValueStartPtr = strstr((char *) message, bc26_data_start_flag)) == NULL) {
            return;//Invalid Data
        } else {
            bc26_cmd = (char *) message + 1;
            bc26_ValueStartPtr++;
            bc26_cmd_len = bc26_ValueStartPtr - bc26_cmd - 2;
            bc26_value_len = bc26_EndPtr - bc26_ValueStartPtr;
            onValueReceive(bc26_cmd, bc26_cmd_len, bc26_ValueStartPtr, bc26_value_len);
            return;
        }
    } else {
        if ((bc26_ValueStartPtr = strstr((char *) message, bc26_OK_Flag)) != NULL) {
            onOKPocketReceive(message, size - 2);
        } else {
            onERRORPocketReceive(message, size - 2);
        }
        return;
    }

    sendMessageUart1_DMA(message, size - 2);


}

void onValueReceive(char *cmd, uint8_t cmd_len, char *val, uint8_t val_len) {
    sendMessageUart1("[BC26_Debug]BC26_Callback: CMD:", 31);
    sendMessageUart1(cmd, cmd_len);
    sendMessageUart1("  VAL: ", 7);
    sendMessageUart1(val, val_len);
    sendMessageUart1("\n", 1);

    if (strstr(cmd, bc26_cmd_CGATT) != NULL) {
        loadParameter(val, val_len);
        bc26_states.online = reader.params[0].numValue;
        if (bc26_states.online == 1) {
            //          sendMessageUart1("[BC26]O0:\n", 10);
            onBC26RegisteredEvent();
        } else {
            //         sendMessageUart1("[BC26]o0:\n", 10);
            onBC26unRegisteredEvent();
        }

        return;
    }
    if (strstr(cmd, bc26_cmd_IP) != NULL) {
        bc26_states.online = 1;
        onBC26unRegisteredEvent();
        return;
    }
    if (strstr(cmd, bc26_cmd_CSQ) != NULL) {
        loadParameter(val, val_len);
        bc26_states.CSQ = reader.params[0].numValue;
        sendMessageUart1("[BC26]Reported CSQ:", 19);
        int len = myitoa(bc26_states.CSQ, bc26_num_buf, 10);
        sendMessageUart1(bc26_num_buf, len);
        sendMessageUart1("\n", 1);
        return;
    }

    if (strstr(cmd, bc26_cmd_QMTCONN) != NULL) {
        loadParameter(val, val_len);
        if (reader.params[1].numValue == 0) {
            onMQTTConnectEvent();
        } else {
            onMQTTConnectFailedEvent(reader.params[1].numValue);
        }
        return;
    }
    if (strstr(cmd, bc26_cmd_QMTSUB) != NULL) {
        loadParameter(val, val_len);
        if (reader.params[1].numValue == 1) {
            onMQTTSubscribetEvent();
        } else {
            onMQTTSubscribeFailedEvent(reader.params[1].numValue);
        }
        return;
    }
    if (strstr(cmd, bc26_cmd_QMTOPEN) != NULL) {
        loadParameter(val, val_len);
        if (reader.params[1].numValue == 0) {
            onBC26SocketConnectEvent();
        } else {
            onBC26SocketConnectFailedEvent(reader.params[1].numValue);
        }
        return;
    }

    if (strstr(cmd, bc26_cmd_QMTPUB) != NULL) {
        loadParameter(val, val_len);
        if (reader.params[1].numValue == 0) {
            onMQTTPublishEvent();
        } else {
            onMQTTPublishFailedEvent(reader.params[1].numValue);
        }
        return;
    }
    if (strstr(cmd, bc26_cmd_QMTRECV) != NULL) {
        loadParameter(val, val_len);
        sendMessageUart1("[BC26]Receive Message From:", 27);
        sendMessageUart1(reader.params[2].StringValuePtr, reader.params[2].invalidValue_len);
        sendMessageUart1("  Values:  ", 11);
        sendMessageUart1(reader.params[3].StringValuePtr, reader.params[3].invalidValue_len);
        sendMessageUart1("\n", 1);
        return;
    }
    if (strstr(cmd, bc26_cmd_QMTSTAT) != NULL) {
        if (reader.params[1].numValue != 0) {
            onBC26SocketDisconnectEvent(reader.params[1].numValue);
            //        sendMessageUart1("[BC26]T0:\n", 10);
        } else {
            //        onBC26SocketConnectEvent();     sendMessageUart1("[BC26]T1:\n", 10);
        }
        return;
    }
    // loadParameter(val,val_len);
    //   cmd;


}


void onERRORPocketReceive(char *cmd, uint8_t len) {
    sendMessageUart1("[BC26]Error:\n", 13);
    sendMessageUart1(cmd, len);
}

void loadParameter(char *value, uint8_t value_len) {
    reader.validParamsAmount = 0;
    Parameter *nowParam;
    uint8_t sumLen = 0;
    if (value_len == 1) {
        nowParam = &reader.params[0];
        nowParam->invalidValue_len = nowParam->value_len;
        nowParam->numValue = myatoi((uint8_t *) value, 1, 10);
        reader.validParamsAmount = 1;
        return;
    }
    char *now_ptr = value;
    char *next_ptr = NULL;
    uint8_t hasNext;
    do {
        hasNext = ((next_ptr = strstr(now_ptr, bc26_param_split_flag)) != NULL);
        nowParam = &reader.params[reader.validParamsAmount];
        nowParam->originValuePtr = now_ptr;
        nowParam->value_len = hasNext ? next_ptr - now_ptr : value_len - sumLen;
        sumLen += nowParam->value_len;
        if (*(now_ptr + 1) == 34) {
            nowParam->StringValuePtr = nowParam->originValuePtr + 1;
            nowParam->invalidValue_len = nowParam->value_len - 2;
        } else {
            nowParam->invalidValue_len = nowParam->value_len;
            nowParam->numValue = myatoi((uint8_t *) now_ptr, nowParam->invalidValue_len, 10);
        }
        reader.validParamsAmount++;
        if (hasNext) {
            now_ptr = next_ptr + 1;
            sumLen++;
        }
    } while (hasNext);

}


void bc26_clearATBuffer() {
    memset(bc26_at_buffer, 0, bc26_now_at_buffer_index);
    bc26_now_at_buffer_index = 0;
    bc26_atAppendString(bc26_ATPlusFlag);
}

void bc26_atAppendString(char *str) {
    for (int i = 0; i <= 255; i++) {
        if (*(str + i) == '\0') {
            break;
        }
        *(bc26_at_buffer + (bc26_now_at_buffer_index++)) = *(str + i);
    }
}

void bc26_atAppendNumber(int num) {
    uint8_t nbuf[20];
    myitoa(num, nbuf, 10);
    bc26_atAppendString((char *) nbuf);
}

void bc26_atAppendHexNumber(int num) {
    uint8_t nbuf[20];
    myitoa(num, nbuf, 16);
    bc26_atAppendString((char *) nbuf);
}

void bc26_sendAtBuffer() {
    bc26_atAppendString(bc26_newLineFlag);
    sendMessageUart3(bc26_at_buffer, bc26_now_at_buffer_index);
    bc26_clearATBuffer();
}

void bc26_appendCMDQ(char *cmd) {
    bc26_atAppendString(cmd);
    bc26_atAppendString("?");
}

void bc26_appendCMD(char *cmd) {
    bc26_atAppendString(cmd);
    bc26_atAppendString("=");
}

void bc26_appendParamNumber(int num, uint8_t last) {
    bc26_atAppendNumber(num);
    if (!last)
        bc26_atAppendString(",");
}

void bc26_appendParamString(char *str, uint8_t last) {
    bc26_atAppendString("\"");
    bc26_atAppendString(str);
    bc26_atAppendString("\"");
    if (!last)
        bc26_atAppendString(",");
}

void bc26_sendCSQ() {
    bc26_atAppendString(bc26_cmd_CSQ);
    bc26_sendAtBuffer();
}

void bc26_sendCGATT() {
    bc26_appendCMDQ(bc26_cmd_CGATT);
    bc26_sendAtBuffer();
}

void bc26_ConnectSocket(char *server, uint16_t port) {
    bc26_appendCMD(bc26_cmd_QMTOPEN);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamString(server, 0);
    bc26_appendParamNumber(port, 1);
    bc26_sendAtBuffer();
}

void bc26_ConnectMQTT(char *name) {
    bc26_appendCMD(bc26_cmd_QMTCONN);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamString(name, 1);
    bc26_sendAtBuffer();
}

void bc26_Subscribe(char *name, uint8_t qos) {
    bc26_appendCMD(bc26_cmd_QMTSUB);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamNumber(1, 0);
    bc26_appendParamString(name, 0);
    bc26_appendParamNumber(qos, 1);
    bc26_sendAtBuffer();
}

void BC26_Slow_1S_Tick() {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        if (bc26_setup.process == BC26_Wait_for_NET_Register) {
            bc26_sendCGATT();
        }
        if (bc26_setup.time_out_second != 0) {
            bc26_setup.now_time++;
            if (bc26_setup.now_time >= bc26_setup.time_out_second) {
                bc26_onTimeout();
            }
        }

    }
    if (bc26_states.Terminal_ready) {
        keepalive.time++;
        if (keepalive.time >= 30) {
            keepalive.time = 0;
            sendKeepAlivePocket();
        }

    }

}

void BC26_Setup_ResetAndSetup() {
    bc26_setup.enable = 1;
    bc26_setup.retry_times = 0;
    bc26_setup.isFault = 0;
    bc26_setup.time_out_second = 0;
    bc26_setup.now_time = 0;
    bc26_setup.time_out_second = 1;
    bc26_setup.process = BC26_Wait_for_NET_Register;
    bc26_sendCGATT();
}

void onOKPocketReceive(char *cmd, uint8_t len) {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        switch (bc26_setup.process) {
            case BC26_Wait_for_MQTT_Connect_Send:
                bc26_setup.process = BC26_Wait_for_MQTT_Connect_Reply;
                return;
            case BC26_Wait_for_Socket_Connect_Send:
                bc26_setup.process = BC26_Wait_for_Socket_Connect_Reply;
                return;
            case BC26_Wait_for_Subscribe_Send:
                bc26_setup.process = BC26_Wait_for_Subscribe_Reply;
                return;
            default:
                return;
        }
    }
}

void bc26_onTimeout() {
    bc26_setup.now_time = 0;
    //TODO TIME OUT HANDLE
}

void setBC26SetupTimeout(uint8_t timeout) {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        bc26_setup.now_time = 0;
        bc26_setup.time_out_second = timeout;
    }
}

void onBC26RegisteredEvent() {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        if (bc26_setup.process == BC26_Wait_for_NET_Register) {
            bc26_setup.process = BC26_Wait_for_Socket_Connect_Send;
            bc26_ConnectSocket(server, port);
            sendMessageUart1_DMA("Sending Socket Connect Request\n", 31);
        }
    }
}

void onBC26SocketConnectEvent() {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        if (bc26_setup.process == BC26_Wait_for_Socket_Connect_Reply) {
            bc26_setup.process = BC26_Wait_for_MQTT_Connect_Send;
            bc26_ConnectMQTT(device_name);
            sendMessageUart1_DMA("Sending MQTT Connect Request\n", 29);
        }
    }
}

void onMQTTConnectEvent() {
    if (bc26_setup.enable && !bc26_setup.isFault) {
        if (bc26_setup.process == BC26_Wait_for_MQTT_Connect_Reply) {
            bc26_setup.process = BC26_Wait_for_Subscribe_Send;
            bc26_Subscribe(sub_name, 0);
            sendMessageUart1_DMA("Sending Subscribe Request\n", 26);
        }
    }
}

void onMQTTSubscribetEvent() {
    bc26_setup.enable = 0;
    sendMessageUart1_DMA("Connect Complete\n", 17);
    bc26_states.Terminal_ready = 1;
}

void onBC26SocketDisconnectEvent(uint8_t err_code) {
    sendMessageUart1_DMA("Disconnected By Server Retrying\n", 32);
    bc26_states.Terminal_ready = 0;
    BC26_Setup_ResetAndSetup();
}

uint8_t bc26_publishTopic(char *topic, char *value) {
    if (!bc26_states.Terminal_ready)return 1;
    if (!publishManager.free)return 2;
    publishManager.free = 0;
    publishManager.topic = topic;
    publishManager.message = value;
    bc26_publishTopicDirect(topic, value);
    publishManager.waiting_for_success = 1;
}

void bc26_publishTopicDirect(char *topic, char *value) {
    bc26_appendCMD(bc26_cmd_QMTPUB);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamNumber(0, 0);
    bc26_appendParamString(topic, 0);
    bc26_appendParamString(value, 1);
    bc26_sendAtBuffer();
}

void sendKeepAlivePocket() {
    bc26_publishTopic(keepAlive, "OK");
}

 void onMQTTPublishEvent(){

}
 void onMQTTPublishFailedEvent(uint8_t code){
    if(publishManager.retryTimes>=3){
        onMQTTPublishTryoutEvent(&publishManager);
    }
    bc26_publishTopicDirect(publishManager.topic,publishManager.message);
     publishManager.retryTimes++;
}